/*
 * #middleware#/key
 */

#ifndef GKT_KEY_H
#define GKT_KEY_H

#include "gkt_keypad.h"

#ifdef __cplusplus
extern "C" {
#endif

#include "gkt_key_defines.h"

#ifdef GKT_CONFIG_KEY_MAP_TABLE
#define GKT_KEY_MAP(key_name)	GKT_KEY_##key_name
static const uint32_t sc_key_map_table[] = {
	GKT_CONFIG_KEY_MAP_TABLE
};
static const uint32_t sc_key_map_table_size = 
			sizeof(sc_key_map_table) / sizeof(uint32_t);

#define channel_2_key(channel)	\
	(((channel) < sc_key_map_table_size) ? \
		sc_key_map_table[channel] : GKT_KEY_MAX)
#endif

/* KEY MINOR TYPE */
#define GKT_KEY_MINOR_EXT_MASK	0xff00
#define GKT_KEY_MINOR_LED_FLICKER_END	(GKT_KEY_MINOR_EXT_MASK | 0)

/* KEY EVENT DATA INDEX */
#define GKT_KEY_EVTDATA_ACTION	0	/* release, short press or long press */
#define GKT_KEY_EVTDATA_REPEAT	1	/* repeat count of long press */

/* voice type */
enum {
	GKT_KEY_VOICE_VALID = 0,
	GKT_KEY_VOICE_INVALID,
	GKT_KEY_VOICE_MAX
};

enum {
	GKT_KEY_LED_CTRL_ENABLE = 0,
	GKT_KEY_LED_CTRL_BRIGHT,
	GKT_KEY_LED_CTRL_ALL_ON,
	GKT_KEY_LED_CTRL_MAX
};

#define GKT_KEY_MASK_F_LED_DETACH	(1U << 0)
#define GKT_KEY_MASK_F_LED_ALL_ON	(1U << 1)

typedef void (*gkt_key_default_handler)(uint32_t *evt_data);

int gkt_key_init(void);

/************************************************************
 * @brief : mask or unmask all keys/keypad
 ************************************************************/
void gkt_key_mask(int masked, uint32_t flags);

/************************************************************
 * @brief : mask / unmask partial keys
 * @precondition: the keypad is unmasked
 ************************************************************/
void gkt_key_mask_partial(uint32_t masked_key_bits);

void gkt_key_register_default_handler(uint32_t key,
			gkt_key_default_handler def_handler);

/************************************************************
 * @brief : set key voice id
 ************************************************************/
#if defined(GKT_CONFIG_VOICE_OUTPUT_ENABLE) && GKT_CONFIG_VOICE_OUTPUT_ENABLE
void gkt_key_voice_set_id(uint32_t type, uint32_t id);
void gkt_key_voice_mask(uint32_t masked_bits);
#else
#define gkt_key_voice_set_id(type, id)	do {} while(0)
#define gkt_key_voice_mask(masked_bits)	do {} while(0)
#endif

#ifdef GKT_CONFIG_KEY_LED_MAP_TABLE

#include "gkt_led.h"

void gkt_key_led_control(uint32_t ctrl, uint32_t data);

#if (!defined(GKT_CONFIG_LED_FLICKER_DISABLE) || !GKT_CONFIG_LED_FLICKER_DISABLE) \
	&& (!defined(GKT_CONFIG_KEY_LED_FLICKER_DISABLE) || !GKT_CONFIG_KEY_LED_FLICKER_DISABLE)
#define GKT_KEY_LED_FLICKER_ENABLE	1

#define GKT_KEY_LED_FLICKER_F_CYCLES_SHIFT	0
#define GKT_KEY_LED_FLICKER_F_CYCLES_BITS	12
#define GKT_KEY_LED_FLICKER_F_CYCLES_MASK	\
	(((1U << GKT_KEY_LED_FLICKER_F_CYCLES_BITS) - 1) << GKT_KEY_LED_FLICKER_F_CYCLES_SHIFT)

#define GKT_KEY_LED_FLICKER_F_FRAME_TIME_SHIFT	\
	(GKT_KEY_LED_FLICKER_F_CYCLES_SHIFT + GKT_KEY_LED_FLICKER_F_CYCLES_BITS)
#define GKT_KEY_LED_FLICKER_F_FRAME_TIME_BITS	16
#define GKT_KEY_LED_FLICKER_F_FRAME_TIME_MASK	\
	(((1U << GKT_KEY_LED_FLICKER_F_FRAME_TIME_BITS) - 1) << GKT_KEY_LED_FLICKER_F_FRAME_TIME_SHIFT)

#define GKT_KEY_LED_FLICKER_F_VOICE_HINT_SHIFT	\
	(GKT_KEY_LED_FLICKER_F_FRAME_TIME_SHIFT + GKT_KEY_LED_FLICKER_F_FRAME_TIME_BITS)
#define GKT_KEY_LED_FLICKER_F_VOICE_HINT	\
	(1U << GKT_KEY_LED_FLICKER_F_VOICE_HINT_SHIFT)

#define GKT_KEY_LED_FLICKER_F_CYCLES_INFINITE_SHIFT	\
	(GKT_KEY_LED_FLICKER_F_VOICE_HINT_SHIFT + 1)
#define GKT_KEY_LED_FLICKER_F_CYCLES_INFINITE	\
	(1U << GKT_KEY_LED_FLICKER_F_CYCLES_INFINITE_SHIFT)

#define GKT_KEY_LED_FLICKER_F_REVERSE_BACK_SHIFT	\
	(GKT_KEY_LED_FLICKER_F_CYCLES_INFINITE_SHIFT + 1)
#define GKT_KEY_LED_FLICKER_F_REVERSE_BACK	\
	(1U << GKT_KEY_LED_FLICKER_F_REVERSE_BACK_SHIFT)

int gkt_key_led_flicker(uint32_t key_bits, uint32_t flags);
int gkt_key_led_marquee(const uint32_t *frames_key_bits, 
			uint32_t frame_nums, uint32_t flags);
#else
#define GKT_KEY_LED_FLICKER_ENABLE	0
#endif
#else
#define GKT_KEY_LED_FLICKER_ENABLE	0
#define gkt_key_led_control(ctrl, data)	do {} while(0)
#endif

void gkt_key_get_unmask_bits(uint32_t *unmask_bits);

void gkt_key_stage(uint16_t key_value, uint32_t data);

void gkt_key_reset(void);

uint32_t gkt_key_wakeup(void);

int gkt_key_calibrate(int force, uint32_t status);

int gkt_key_wakeup_resume_parameter(void);
	
int gkt_key_parameter_update(uint32_t response);

void gkt_key_enable_long_press(uint32_t bits);
void gkt_key_disable_long_press(uint32_t bits);

#ifdef __cplusplus
}
#endif

#endif	/* GKT_KEY_H */

